home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / TUTOROOT.PAK / STEP09.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  10KB  |  449 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1994 by Borland International
  3. //   Tutorial application -- step09.cpp
  4. //----------------------------------------------------------------------------
  5. #include <owl/pch.h>
  6. #include <owl/applicat.h>
  7. #include <owl/framewin.h>
  8. #include <owl/dc.h>
  9. #include <owl/inputdia.h>
  10. #include <owl/opensave.h>
  11. #include <owl/gdiobjec.h>
  12. #include <owl/chooseco.h>
  13. #include <classlib/arrays.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "step09.rc"
  17.  
  18. typedef TArray<TPoint> TPoints;
  19. typedef TArrayIterator<TPoint> TPointsIterator;
  20.  
  21. class TLine : public TPoints {
  22.   public:
  23.     // Constructor to allow construction from a color and a pen size.
  24.     // Also serves as default constructor.
  25.     TLine(const TColor& color = TColor(0), int penSize = 1) :
  26.       TPoints(10, 0, 10), PenSize(penSize), Color(color) {}
  27.  
  28.     // Functions to modify and query pen attributes.
  29.     int QueryPenSize() const
  30.     {
  31.       return PenSize;
  32.     }
  33.  
  34.     TColor& QueryColor()
  35.     {
  36.       return Color;
  37.     }
  38.  
  39.     void SetPen(const TColor& newColor, int penSize = 0);
  40.     void SetPen(int penSize);
  41.  
  42.     // TLine draws itself.  Returns true if everything went OK.
  43.     virtual bool Draw(TDC&) const;
  44.  
  45.     // The == operator must be defined for the container class, even if unused
  46.     bool operator ==(const TLine& other) const
  47.     {
  48.       return &other == this;
  49.     }
  50.  
  51.     friend ostream& operator <<(ostream& os, const TLine& line);
  52.     friend istream& operator >>(istream& is, TLine& line);
  53.  
  54.   protected:
  55.     int PenSize;
  56.     TColor Color;
  57. };
  58.  
  59. void
  60. TLine::SetPen(int penSize)
  61. {
  62.   if (penSize < 1)
  63.     PenSize = 1;
  64.   else
  65.     PenSize = penSize;
  66. }
  67.  
  68. void
  69. TLine::SetPen(const TColor& newColor, int penSize)
  70. {
  71.   // If penSize isn't the default (0), set PenSize to the new size.
  72.   if (penSize)
  73.     PenSize = penSize;
  74.  
  75.   Color = newColor;
  76. }
  77.  
  78. bool
  79. TLine::Draw(TDC& dc) const
  80. {
  81.   // Set pen for the dc to the values for this line
  82.   TPen pen(Color, PenSize);
  83.   dc.SelectObject(pen);
  84.  
  85.   // Iterates through the points in the line i.
  86.   TPointsIterator j(*this);
  87.   bool first = true;
  88.  
  89.   while (j) {
  90.     TPoint p = j++;
  91.  
  92.     if (!first)
  93.       dc.LineTo(p);
  94.     else {
  95.       dc.MoveTo(p);
  96.       first = false;
  97.     }
  98.   }
  99.   dc.RestorePen();
  100.   return true;
  101. }
  102.  
  103. typedef TArray<TLine> TLines;
  104. typedef TArrayIterator<TLine> TLinesIterator;
  105.  
  106. class TDrawWindow : public TWindow {
  107.   public:
  108.     TDrawWindow(TWindow* parent = 0);
  109.    ~TDrawWindow()
  110.     {
  111.       delete DragDC;
  112.       delete Line;
  113.       delete Lines;
  114.       delete FileData;
  115.     }
  116.  
  117.   protected:
  118.     TDC* DragDC;
  119.     TPen* Pen;
  120.     TLines* Lines;
  121.     TLine* Line; // To hold a single line at a time that later gets
  122.                  // stuck in Lines
  123.     TOpenSaveDialog::TData* FileData;
  124.     bool IsDirty, IsNewFile;
  125.  
  126.     void GetPenSize(); // GetPenSize always calls Line->SetPen().
  127.  
  128.     // Override member function of TWindow
  129.     bool CanClose();
  130.  
  131.     // Message response functions
  132.     void EvLButtonDown(uint, TPoint&);
  133.     void EvRButtonDown(uint, TPoint&);
  134.     void EvMouseMove(uint, TPoint&);
  135.     void EvLButtonUp(uint, TPoint&);
  136.     void Paint(TDC&, bool, TRect&);
  137.     void CmFileNew();
  138.     void CmFileOpen();
  139.     void CmFileSave();
  140.     void CmFileSaveAs();
  141.     void CmPenSize();
  142.     void CmPenColor();
  143.     void CmAbout();
  144.     void SaveFile();
  145.     void OpenFile();
  146.  
  147.   DECLARE_RESPONSE_TABLE(TDrawWindow);
  148. };
  149.  
  150. DEFINE_RESPONSE_TABLE1(TDrawWindow, TWindow)
  151.   EV_WM_LBUTTONDOWN,
  152.   EV_WM_RBUTTONDOWN,
  153.   EV_WM_MOUSEMOVE,
  154.   EV_WM_LBUTTONUP,
  155.   EV_COMMAND(CM_FILENEW, CmFileNew),
  156.   EV_COMMAND(CM_FILEOPEN, CmFileOpen),
  157.   EV_COMMAND(CM_FILESAVE, CmFileSave),
  158.   EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
  159.   EV_COMMAND(CM_PENSIZE, CmPenSize),
  160.   EV_COMMAND(CM_PENCOLOR, CmPenColor),
  161.   EV_COMMAND(CM_ABOUT, CmAbout),
  162. END_RESPONSE_TABLE;
  163.  
  164. TDrawWindow::TDrawWindow(TWindow* parent)
  165. {
  166.   Init(parent, 0, 0);
  167.   DragDC    = 0;
  168.   Lines     = new TLines(5, 0, 5);
  169.   Line      = new TLine(TColor::Black, 1);
  170.   IsNewFile = true;
  171.   IsDirty   = false;
  172.   FileData  = new TOpenSaveDialog::TData(OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,
  173.                                         "Point Files (*.PTS)|*.pts|", 0, "",
  174.                                         "PTS");
  175. }
  176.  
  177. bool
  178. TDrawWindow::CanClose()
  179. {
  180.   if (IsDirty)
  181.     switch(MessageBox("Do you want to save?", "Drawing has changed",
  182.                       MB_YESNOCANCEL | MB_ICONQUESTION)) {
  183.       case IDCANCEL:
  184.         // Choosing Cancel means to abort the close -- return false.
  185.         return false;
  186.  
  187.       case IDYES:
  188.         // Choosing Yes means to save the drawing.
  189.         CmFileSave();
  190.     }
  191.   return true;
  192. }
  193.  
  194. void
  195. TDrawWindow::EvLButtonDown(uint, TPoint& point)
  196. {
  197.   if (!DragDC) {
  198.     SetCapture();
  199.     DragDC = new TClientDC(*this);
  200.     Pen = new TPen(Line->QueryColor(), Line->QueryPenSize());
  201.     DragDC->SelectObject(*Pen);
  202.     DragDC->MoveTo(point);
  203.     Line->Add(point);
  204.     IsDirty = true;
  205.   }
  206. }
  207.  
  208. void
  209. TDrawWindow::EvRButtonDown(uint, TPoint&)
  210. {
  211.   GetPenSize();
  212. }
  213.  
  214. void
  215. TDrawWindow::EvMouseMove(uint, TPoint& point)
  216. {
  217.   if (DragDC) {
  218.     DragDC->LineTo(point);
  219.     Line->Add(point);
  220.   }
  221. }
  222.  
  223. void
  224. TDrawWindow::EvLButtonUp(uint, TPoint&)
  225. {
  226.   if (DragDC) {
  227.     ReleaseCapture();
  228.     Lines->Add(*Line);
  229.     Line->Flush();
  230.     delete DragDC;
  231.     delete Pen;
  232.     DragDC = 0;
  233.   }
  234. }
  235.  
  236. void
  237. TDrawWindow::CmPenSize()
  238. {
  239.   GetPenSize();
  240. }
  241.  
  242. void
  243. TDrawWindow::CmPenColor()
  244. {
  245.   TChooseColorDialog::TData colors;
  246.   static TColor custColors[16] =
  247.   {
  248.     0x010101L, 0x101010L, 0x202020L, 0x303030L,
  249.     0x404040L, 0x505050L, 0x606060L, 0x707070L,
  250.     0x808080L, 0x909090L, 0xA0A0A0L, 0xB0B0B0L,
  251.     0xC0C0C0L, 0xD0D0D0L, 0xE0E0E0L, 0xF0F0F0L
  252.   };
  253.  
  254.   colors.Flags = CC_RGBINIT;
  255.   colors.Color = TColor(Line->QueryColor());
  256.   colors.CustColors = custColors;
  257.   if (TChooseColorDialog(this, colors).Execute() == IDOK)
  258.     Line->SetPen(colors.Color);
  259. }
  260.  
  261. void
  262. TDrawWindow::GetPenSize()
  263. {
  264.   char inputText[6];
  265.   int penSize = Line->QueryPenSize();
  266.  
  267.   wsprintf(inputText, "%d", penSize);
  268.   if ((TInputDialog(this, "Line Thickness",
  269.                         "Input a new thickness:",
  270.                         inputText,
  271.                         sizeof(inputText))).Execute() == IDOK) {
  272.     penSize = atoi(inputText);
  273.  
  274.     if (penSize < 1)
  275.       penSize = 1;
  276.   }
  277.   Line->SetPen(penSize);
  278. }
  279.  
  280. void
  281. TDrawWindow::Paint(TDC& dc, bool, TRect&)
  282. {
  283.   // Iterates through the array of line objects.
  284.   TLinesIterator i(*Lines);
  285.  
  286.   while (i)
  287.     i++.Draw(dc);
  288. }
  289.  
  290. void
  291. TDrawWindow::CmFileNew()
  292. {
  293.   if (CanClose()) {
  294.     Line->Flush();
  295.     Lines->Flush();
  296.     Invalidate();
  297.     IsDirty = false;
  298.     IsNewFile = true;
  299.   }
  300. }
  301.  
  302. void
  303. TDrawWindow::CmFileOpen()
  304. {
  305.   if (CanClose())
  306.     if ((TFileOpenDialog(this, *FileData)).Execute() == IDOK)
  307.       OpenFile();
  308. }
  309.  
  310. void
  311. TDrawWindow::CmFileSave()
  312. {
  313.   if (IsNewFile)
  314.     CmFileSaveAs();
  315.   else
  316.     SaveFile();
  317. }
  318.  
  319. void
  320. TDrawWindow::CmFileSaveAs()
  321. {
  322.   if (IsNewFile)
  323.     strcpy(FileData->FileName, "");
  324.  
  325.   if ((TFileSaveDialog(this, *FileData)).Execute() == IDOK)
  326.     SaveFile();
  327. }
  328.  
  329. void
  330. TDrawWindow::CmAbout()
  331. {
  332.   TDialog(this, IDD_ABOUT).Execute();
  333. }
  334.  
  335. void
  336. TDrawWindow::SaveFile()
  337. {
  338.   ofstream os(FileData->FileName);
  339.  
  340.   if (!os)
  341.     MessageBox("Unable to open file", "File Error", MB_OK | MB_ICONEXCLAMATION);
  342.   else {
  343.     // Write the number of lines in the figure
  344.     os << Lines->GetItemsInContainer();
  345.  
  346.     // Append a description using a resource string
  347.     os << ' ' << string(*GetApplication(), IDS_FILEINFO) << '\n';
  348.  
  349.     // Get an iterator for the array of lines
  350.     TLinesIterator i(*Lines);
  351.  
  352.     // While the iterator is valid (i.e. we haven't run out of lines)
  353.     while (i)
  354.       // Copy the current line from the iterator and increment the array.
  355.       os << i++;
  356.  
  357.     // Set new file and dirty display indicator to false.
  358.     IsNewFile = IsDirty = false;
  359.   }
  360. }
  361.  
  362. void
  363. TDrawWindow::OpenFile()
  364. {
  365.   ifstream is(FileData->FileName);
  366.  
  367.   if (!is)
  368.     MessageBox("Unable to open file", "File Error", MB_OK | MB_ICONEXCLAMATION);
  369.   else {
  370.     unsigned numLines;
  371.     char fileinfo[100];
  372.  
  373.     Lines->Flush();
  374.     Line->Flush();
  375.  
  376.     is >> numLines;
  377.     is.getline(fileinfo, sizeof(fileinfo));
  378.     Parent->SetCaption(fileinfo);
  379.  
  380.     for (int i = 0; i < numLines; i++) {
  381.       TLine line;
  382.       is >> line;
  383.       Lines->Add(line);
  384.     }
  385.   }
  386.   IsNewFile = IsDirty = false;
  387.   Invalidate();
  388. }
  389.  
  390. class TDrawApp : public TApplication {
  391.   public:
  392.     TDrawApp() : TApplication() {}
  393.  
  394.     void InitMainWindow()
  395.     {
  396.       SetMainWindow(new TFrameWindow(0, "Drawing Pad", new TDrawWindow));
  397.       GetMainWindow()->AssignMenu("COMMANDS");
  398.     }
  399. };
  400.  
  401. int
  402. OwlMain(int /*argc*/, char* /*argv*/ [])
  403. {
  404.   return TDrawApp().Run();
  405. }
  406.  
  407. ostream&
  408. operator <<(ostream& os, const TLine& line)
  409. {
  410.   // Write the number of points in the line
  411.   os << line.GetItemsInContainer();
  412.  
  413.   // Get and write pen attributes.
  414.   os << ' ' << line.Color << ' ' << line.PenSize;
  415.  
  416.   // Get an iterator for the array of points
  417.   TPointsIterator j(line);
  418.  
  419.   // While the iterator is valid (i.e. we haven't run out of points)
  420.   while(j)
  421.     // Write the point from the iterator and increment the array.
  422.     os << j++;
  423.   os << '\n';
  424.  
  425.   // return the stream object
  426.   return os;
  427. }
  428.  
  429. istream&
  430. operator >>(istream& is, TLine& line)
  431. {
  432.   unsigned numPoints;
  433.   is >> numPoints;
  434.  
  435.   COLORREF color;
  436.   int penSize;
  437.   is >> color >> penSize;
  438.   line.SetPen(TColor(color), penSize);
  439.  
  440.   while (numPoints--) {
  441.     TPoint point;
  442.     is >> point;
  443.     line.Add(point);
  444.   }
  445.  
  446.   // return the stream object
  447.   return is;
  448. }
  449.